#include "DecompFrame.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "../core/stb_image_write.h"

DecompFrame::DecompFrame(wxWindow* parent) :
  wxPanel(parent,wxID_ANY)
{
  filePicker=new wxFilePickerCtrl(this,(int)DecompFrameID::filePicker,wxEmptyString,wxFileSelectorPromptStr,wxT("StrmBMP (*.StrmBMP)|*.StrmBMP"),wxDefaultPosition,wxDefaultSize,wxFLP_OPEN);
  dirPicker=new wxDirPickerCtrl(this,(int)DecompFrameID::dirPicker);
  btnDecomp=new wxButton(this,(int)DecompFrameID::btnDecomp,wxT("解压文件"));
  listInf=new wxListCtrl(this,(int)DecompFrameID::listInf,wxDefaultPosition,wxDefaultSize,wxLC_REPORT);
  wxFlexGridSizer* gridSizer=new wxFlexGridSizer(2,5,5);
  gridSizer->AddGrowableCol(1,1);
  gridSizer->Add(new wxStaticText(this,wxID_ANY,wxT("目标文件")));
  gridSizer->Add(filePicker,wxSizerFlags(0).Expand());
  gridSizer->Add(new wxStaticText(this,wxID_ANY,wxT("解压目录")));
  gridSizer->Add(dirPicker,wxSizerFlags(0).Expand());
  wxBoxSizer* mainSizer=new wxBoxSizer(wxVERTICAL);
  mainSizer->Add(gridSizer,wxSizerFlags(0).Expand());
  mainSizer->Add(btnDecomp,wxSizerFlags(0).Expand());
  mainSizer->AddSpacer(5);
  mainSizer->Add(listInf,wxSizerFlags(6).Expand());

  listInf->InsertColumn(0,wxT("属性名"));
  listInf->InsertColumn(1,wxT("属性值"));
  listInf->SetColumnWidth(0,170);
  listInf->SetColumnWidth(1,300);
  listInf->InsertItem(0,wxT("版本字符串"));
  listInf->InsertItem(1,wxT("文件头大小"));
  listInf->InsertItem(2,wxT("图像数据块大小"));
  listInf->InsertItem(3,wxT("附加数据块大小"));
  listInf->InsertItem(4,wxT("图像宽度"));
  listInf->InsertItem(5,wxT("图像高度"));
  listInf->InsertItem(6,wxT("像素构成种类"));
  listInf->InsertItem(7,wxT("采样分辨率"));
  listInf->InsertItem(8,wxT("操作员姓名"));
  listInf->InsertItem(9,wxT("观测对象"));
  listInf->InsertItem(10,wxT("观测环境"));
  listInf->InsertItem(11,wxT("原始文件名"));
  listInf->InsertItem(12,wxT("文件创建时间"));
  listInf->InsertItem(13,wxT("相机名称"));
  listInf->InsertItem(14,wxT("相机增益"));
  listInf->InsertItem(15,wxT("黑底偏置"));
  listInf->InsertItem(16,wxT("曝光时间"));
  listInf->InsertItem(17,wxT("图像信息采集帧"));
  listInf->InsertItem(18,wxT("附加信息采集频率"));
  listInf->InsertItem(19,wxT("附加通道使能"));
  listInf->InsertItem(20,wxT("附加信息通道名称"));
  listInf->InsertItem(21,wxT("附加信息单位"));
  listInf->InsertItem(22,wxT("附加信息标定系数"));

  SetSizer(mainSizer);

  Bind(wxEVT_FILEPICKER_CHANGED,&DecompFrame::on_filePicker_click,this,(int)DecompFrameID::filePicker);
  Bind(wxEVT_BUTTON,&DecompFrame::on_btnDecomp_click,this,(int)DecompFrameID::btnDecomp);
}


void DecompFrame::on_btnDecomp_click(wxCommandEvent& event)
{
  std::string filePath=filePicker->GetPath().utf8_string();
  std::string dirPath=dirPicker->GetPath().utf8_string();
  if(filePath.length()==0 || dirPath.length()==0)
  {
    wxMessageBox(wxT("请选择一个路径"),wxT("错误"),wxOK,this);
    return;
  }
  if(!std::filesystem::exists(dirPath) || !std::filesystem::exists(filePath))
  {
    wxMessageBox(wxT("所选择的路径无效"),wxT("错误"),wxOK,this);
    return;
  }
  std::filesystem::path outputPath(dirPath);
  std::ofstream TimeFile(outputPath/"ImageTime.txt");
  std::ofstream AdditionalFile(outputPath/"Additional.txt",std::ios::trunc);
  if(!TimeFile.is_open() || !AdditionalFile.is_open())
  {
    wxMessageBox(wxT("无法打开文件输出"),wxT("错误"),wxOK,this);
    return;
  }
  try
  {
    StrmBMP_reader reader(filePath);
    wxProgressDialog progDlg(wxT("正在执行"),wxT("正在处理图像"),reader.GetImageSize(),this);
    reader.BeginReadBMP();
    std::pair<imageBlockHead,char*> ImageFrame;
    long count=0;
    stbi_flip_vertically_on_write(true);
    do{
      ImageFrame=reader.GetImageFrame();
      if(ImageFrame.second!=nullptr)
      {
        stbi_write_bmp(
            (outputPath/fmt::format("{}.bmp",ImageFrame.first.Index)).string().c_str(),
            reader.GetFileHead().imageWidth,
            reader.GetFileHead().imageHeight,
            reader.GetFileHead().pixelType,
            ImageFrame.second
        );
        TimeFile<<ImageFrame.first.Time<<' ';
        delete [] ImageFrame.second;
      }
      else
      {
        if(count!=progDlg.GetRange())
        {
          wxMessageBox(wxT("输出校验失败，请检查文件属否损坏"),wxT("错误"),wxOK,this);
          return;
        }
        break;
      }
      progDlg.Update(count,wxString::Format(L"正在处理图像 %ld 张",count));
      count++;
    }while(true);
    TimeFile.close();
    TimeFile.open(outputPath/"AdditionalTime.txt",std::ios::trunc);
    if(!TimeFile.is_open())
    {
      wxMessageBox(wxT("无法输出Additional.txt文件"),wxT("错误"),wxOK,this);
      return;
    }
    progDlg.Update(progDlg.GetRange()-1,wxT("正在处理附加数据"));
    reader.BeginReadAdditional();
    while(true)
    {
      try
      {
        additionalBlockHead Additional=reader.GetAdditionalFrame();
        TimeFile<<Additional.Time<<' ';
        AdditionalFile<<Additional.value<<' ';
      }
      catch(...)
      {
        break;
      }
    }
  }
  catch(...)
  {
    wxMessageBox(wxT("文件解压失败"),wxT("错误"),wxOK,this);
    return;
  }
}

void DecompFrame::on_filePicker_click(wxFileDirPickerEvent& event)
{
  std::string filePath=filePicker->GetPath().utf8_string();
  if(filePath.length()==0)
    return;
  try 
  {
    StrmBMP_reader reader(filePicker->GetPath().utf8_string());
    fileHead Header=reader.GetFileHead();
    listInf->SetItem(0,1,wxString::FromUTF8(GetFileHeadAttributeValue(Header.Version,sizeof(Header.Version)/sizeof(char16_t))));
    listInf->SetItem(1,1,wxString::Format("%d",Header.HeadLength));
    listInf->SetItem(2,1,wxString::Format("%lld",Header.imageDataBlockLength));
    listInf->SetItem(3,1,wxString::Format("%lld",Header.additionalBlockLength));
    listInf->SetItem(4,1,wxString::Format("%u",Header.imageWidth));
    listInf->SetItem(5,1,wxString::Format("%u",Header.imageHeight));
    listInf->SetItem(6,1,wxString::Format("%d",Header.pixelType));
    listInf->SetItem(7,1,wxString::Format("%d",Header.SamplingResolution));
    listInf->SetItem(8,1,wxString::FromUTF8(GetFileHeadAttributeValue(Header.OperatorName,sizeof(Header.OperatorName)/sizeof(char16_t))));
    listInf->SetItem(9,1,wxString::FromUTF8(GetFileHeadAttributeValue(Header.ViewTarget,sizeof(Header.ViewTarget)/sizeof(char16_t))));
    listInf->SetItem(10,1,wxString::FromUTF8(GetFileHeadAttributeValue(Header.ViewEnvironment,sizeof(Header.ViewEnvironment)/sizeof(char16_t))));
    listInf->SetItem(11,1,wxString::FromUTF8(GetFileHeadAttributeValue(Header.FileName,sizeof(Header.FileName)/sizeof(char16_t))));
    listInf->SetItem(12,1,wxString::Format("%lld",Header.FileCreateTime));
    listInf->SetItem(13,1,wxString::FromUTF8(GetFileHeadAttributeValue(Header.cameraName,sizeof(Header.cameraName)/sizeof(char16_t))));
    listInf->SetItem(14,1,wxString::Format("%f",Header.cameraGain));
    listInf->SetItem(15,1,wxString::Format("%f",Header.cameraBlackOffset));
    listInf->SetItem(16,1,wxString::Format("%d",Header.cameraExpourseTime));
    listInf->SetItem(16,1,wxString::Format("%d",Header.cameraExpourseTime));
    listInf->SetItem(17,1,wxString::Format("%d",Header.imageCollegeInfFrame));
    listInf->SetItem(18,1,wxString::Format("%d",Header.additionalInfCollegeRate));
    listInf->SetItem(19,1,wxString::Format("%d",Header.additionalChannelEnable));
    listInf->SetItem(20,1,wxString::FromUTF8(GetFileHeadAttributeValue(Header.additionalChannelName,sizeof(Header.additionalChannelName)/sizeof(char16_t))));
    listInf->SetItem(21,1,wxString::FromUTF8(GetFileHeadAttributeValue(Header.additionalChannelUnit,sizeof(Header.additionalChannelUnit)/sizeof(char16_t))));
    listInf->SetItem(22,1,wxString::Format("%d",Header.additionalDemarcate));
  } 
  catch (...) 
  {
  }
}

